package cn.asoul.domain.strategy.service.armory;

import cn.asoul.domain.strategy.model.entity.StrategyAwardEntity;
import cn.asoul.domain.strategy.repostory.IStrategyRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.security.SecureRandom;
import java.util.*;

/**
 * @description: 策略装配库，负责初始化策略计算
 * @author: chen
 * @date: 2025/3/6 15:33
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class StrategyArmory implements IStrategyArmory {
    private final IStrategyRepository repository;

    public boolean assembleLotteryStrategy(Long strategyId) {
        // 查询策略配置
        List<StrategyAwardEntity> strategyAwardEntityList = repository.queryStrategyAwardList(strategyId);

        if (strategyAwardEntityList == null || strategyAwardEntityList.isEmpty()) {
            return false;
        }

        // 获取最小的概率
        BigDecimal minAwardRate = strategyAwardEntityList.stream()
                .map(StrategyAwardEntity::getAwardRate)
                .min(BigDecimal::compareTo)
                .orElse(BigDecimal.ZERO);
        // 获取总概率
        BigDecimal totalAwardRate = strategyAwardEntityList.stream()
                .map(StrategyAwardEntity::getAwardRate)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 获取总范围
        BigDecimal rateRange = totalAwardRate.divide(minAwardRate, 0, RoundingMode.CEILING);

        // 根据当前概率在总概率中的占比获取他的范围
        ArrayList<Integer> strategyAwardSearchRateTable = new ArrayList<>(rateRange.intValue());

        strategyAwardEntityList.forEach(strategyAwardEntity -> {
            Integer awardId = strategyAwardEntity.getAwardId();
            for (int i = 0; i < rateRange.multiply(strategyAwardEntity.getAwardRate()).setScale(0, RoundingMode.CEILING).intValue(); i++) {
                strategyAwardSearchRateTable.add(awardId);
            }
        });

        Collections.shuffle(strategyAwardSearchRateTable);

        HashMap<Integer, Integer> shuffledStrategyAwardSearchRateTable = new HashMap<>(strategyAwardSearchRateTable.size());

        for (int i = 0; i < strategyAwardSearchRateTable.size(); i++) {
            shuffledStrategyAwardSearchRateTable.put(i, strategyAwardSearchRateTable.get(i));
        }

        repository.storeStrategyAwardSearchRateTable(strategyId, shuffledStrategyAwardSearchRateTable);
        return true;
    }

    @Override
    public Integer getRandomAwardId(Long strategyId) {
        Integer rateRange = repository.getRateRange(strategyId);
        return repository.getStrategyAwardAssemble(strategyId, new SecureRandom().nextInt(rateRange));
    }
}
